﻿Public Class Form1
    Private Declare Function SetParent Lib "user32" Alias "SetParent" (ByVal hWndChild As Integer, ByVal hWndNewParent As Integer) As Integer
    Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Integer) As Int16
    Private Declare Function WindowFromPoint Lib "user32" Alias "WindowFromPoint" (ByVal xPoint As Integer, ByVal yPoint As Integer) As Integer
    Private Const VK_LBUTTON = &H1
    Dim t As Threading.Thread
    Dim currentHold As Boolean = False
    Dim currentHandle As Integer
    Dim originParent As Integer
    Private Sub KeepUp()
        While True
            Threading.SpinWait.SpinUntil(Function() False, 100)
            Invoke(New vSetTop(AddressOf SetTop))
        End While
    End Sub
    Private Delegate Sub vSetTop()
    Private Sub SetTop()
        If currentHold = True Then
            Me.TopMost = True
        Else
            Me.TopMost = False
        End If
    End Sub
    Private Sub WatchMouse()
        Dim iCurrentHwnd As Integer = 0
        Dim activeState As Integer = 0
        Dim tx, ty As Integer
        Dim x, y As Integer
        Dim fX, fY As Integer
        While True
            Threading.SpinWait.SpinUntil(Function() False, 100)
            tx = Me.Left + (Me.Width - Me.ClientSize.Width) / 2
            ty = Me.Top + (Me.Width - Me.ClientSize.Width) / 2 + SystemInformation.CaptionHeight
            x = Windows.Forms.Cursor.Position.X
            y = Windows.Forms.Cursor.Position.Y
            fX = x - tx
            fY = y - ty
            If fX > PictureBox1.Left AndAlso fX < PictureBox1.Left + PictureBox1.Width AndAlso fY > PictureBox1.Top AndAlso fY < PictureBox1.Top + PictureBox1.Height Then
                If activeState = 1 AndAlso GetAsyncKeyState(VK_LBUTTON) = 0 Then
                    'if is was in,and 
                    activeState = 0
                    If iCurrentHwnd = Invoke(New vGetProp(AddressOf GetProp), "mehandle") Then
                    ElseIf iCurrentHwnd = 0 Then
                    Else

                        Invoke(New vSetHandle(AddressOf SetHandle), iCurrentHwnd, Invoke(New vGetProp(AddressOf GetProp), "groupboxhandle"))
                    End If
                    Continue While
                End If
                If GetAsyncKeyState(VK_LBUTTON) <> 0 Then
                    '当鼠标处于这个地方的时候，并且鼠标当前是按下的，才会将handle设置
                    iCurrentHwnd = WindowFromPoint(x, y)
                    activeState = 1
                End If
            Else
                activeState = 0
                'remove the handle immediately
                iCurrentHwnd = 0
            End If

        End While
    End Sub

    Private Delegate Sub vSetHandle(ByVal hWnd As Integer, ByVal NewParent As Integer)
    Private Sub SetHandle(ByVal hWnd As Integer, ByVal NewParent As Integer)
        If hWnd = PictureBox1.Handle Then
            Exit Sub
        End If
        currentHandle = hWnd
        originParent = SetParent(hWnd, GroupBox1.Handle)
        currentHold = True
    End Sub
    Private Sub FreeHandle(ByVal hWnd As Integer)
        SetParent(hWnd, originParent)
        currentHold = False
    End Sub

    Private Delegate Function vGetProp(ByVal Propertys As String) As Integer
    Private Function GetProp(ByVal Propertys As String) As Integer
        Select Case Propertys
            Case "picturehandle"
                Return PictureBox1.Handle
            Case "groupboxhandle"
                Return GroupBox1.Handle
            Case "mehandle"
                Return Me.Handle
            Case Else
                Return 0
        End Select
    End Function
    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        Try
            t.Abort()
        Catch ex As Exception

        End Try
        End
    End Sub

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        t = New Threading.Thread(AddressOf WatchMouse)
        t.Start()

        Dim k As New Threading.Thread(AddressOf KeepUp)
        k.Start()
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        FreeHandle(currentHandle)
    End Sub

    Private Sub Form1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
        GroupBox1.Width = Me.Width - 20
        GroupBox1.Height = Me.Height - GroupBox1.Top - 40
    End Sub
End Class
